package com.gxy.learn.backup.shiroauth.shiro.config;

import com.gxy.learn.backup.shiroauth.entity.SysUser;
import com.gxy.learn.backup.shiroauth.service.SysMenuService;
import com.gxy.learn.backup.shiroauth.service.SysRoleService;
import com.gxy.learn.backup.shiroauth.service.SysUserService;
import com.gxy.learn.cu.utils.encrypt.md5.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;


/**
 * Description(自定义的ShiroRealm，用于进行用户验证)
 * author: Gao xueyong
 * Create at: 2022/1/4 下午10:53
 */
public class ShiroRealm extends AuthorizingRealm {

    protected SysUserService sysUserService;
    protected SysRoleService sysRoleService;
    protected SysMenuService sysMenuService;

    public ShiroRealm(SysUserService sysUserService, SysRoleService sysRoleService, SysMenuService sysMenuService) {
        this.sysUserService = sysUserService;
        this.sysRoleService = sysRoleService;
        this.sysMenuService = sysMenuService;
        /**
         * 这里匹配数据库里的密码类型 根据需求修改
         */
        this.setCredentialsMatcher(new HashedCredentialsMatcher(Md5Hash.ALGORITHM_NAME));
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 授权，即向通过认证的用户赋予指定的权限
     * 每次通过Shiro获取权限/判断权限时均会触发此方法
     * 当配置缓存后，此方法在当次登录后，仅对当前用户仅调用一次(缓存未过期的情况下)
     * 当退出系统时，会自动清除缓存
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        String token = (String) principals.getPrimaryPrincipal();
//        String loginName = JwtUtil.getUsername(token);
//        SysUser sysUser = sysUserService.getByLoginName(loginName);
//        if (null == sysUser) {
//            return new SimpleAuthorizationInfo();
//        }
//        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//        List<SysUserRoleVO> sysRoles = sysRoleService.getSysRolesByAccount(loginName);
//        List<UserMenuVO> sysMenus = sysMenuService.getSysMenuByAccount(loginName);
//        authorizationInfo.addRoles(sysRoles.stream().map(SysUserRoleVO::getRoleCode).collect(Collectors.toSet()));
//        authorizationInfo.addStringPermissions(sysMenus.stream().map(UserMenuVO::getPermission).collect(Collectors.toSet()));
        return new SimpleAuthorizationInfo();
    }


    /**
     * 身份认证方法
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken userpasswordToken = (UsernamePasswordToken) authenticationToken;
        String loginName = userpasswordToken.getUsername();
        SysUser sysUser = sysUserService.getByLoginName(loginName);
        if (sysUser == null) {
            throw new UnknownAccountException("用户不存在！");
        }
        /**
         * 各种自定义验证
         */



        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(loginName, MD5Util.md5(sysUser.getPassword()), getName());

        //如果验证通过，那么清除上次授权的缓存
        if (StringUtils.equals(loginName, sysUser.getLoginName())) {
            clearCache(authenticationInfo.getPrincipals());
            clearCachedAuthorizationInfo(authenticationInfo.getPrincipals());
        }
        return authenticationInfo;
    }

    /**
     * 清空用户关联权限认证，待下次使用时重新加载。
     * 当异常退出时（如非法关闭浏览器等），缓存不会自动清除，那么就需要手动清除
     *
     * @param principal
     */
    public void clearCachedAuthorizationInfo(String principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        clearCachedAuthorizationInfo(principals);
    }
}
